home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Sound / Tracker / PTSUP2.LHA / PT Support archive / Sources / SoundFX.S < prev   
Encoding:
Text File  |  1995-10-17  |  14.5 KB  |  577 lines

  1.  
  2. SFX__BuffSize    =    286            ; Must be an even number!
  3. SFX__FastMode    =    0
  4. SFX__Debug    =    1
  5. SFX__Mode    =    1
  6.  
  7. Go        move.w    #248,d0
  8.         bsr.w    SFX_Init        ; Initialize with fairly low
  9.                         ; rate. (This makes us use
  10.                         ; samples with low frequencies,
  11.                         ; which again saves memory!)
  12.         beq.s    .Quit
  13.  
  14.         moveq.l    #0,d0
  15.         lea.l    Sample1,a0
  16.         lea.l    Sample1End,a1
  17.         bsr.w    SFX_StartSound        ; Start sample 1
  18.  
  19.         moveq.l    #1,d0
  20.         lea.l    Sample2,a0
  21.         lea.l    Sample2End,a1
  22.         bsr.w    SFX_StartSound        ; Start sample 2
  23.  
  24. .a        cmp.b    #$ff,$dff006
  25.         bne.s    .a
  26. .b        cmp.b    #$ff,$dff006
  27.         beq.s    .b
  28.  
  29.         btst    #6,$bfe001        ; Wait for mouse
  30.         bne.s    .a
  31.  
  32. .Quit        bsr.w    SFX_End            ; End
  33.  
  34.         moveq.l    #0,d0            ; Successful exit
  35.         rts
  36.  
  37. ;------------------------------------------------------------------------------
  38. ;
  39. ;    $VER: SoundFX v1.2 sound replay - by Håvard "Howard" Pedersen
  40. ;    © 1994-95 Mental Diseases
  41. ;
  42. ;    A simple program for handling the replay of multiple soundeffects
  43. ;    through a single audio channel.
  44. ;
  45. ;    I cannot be held responsible for any damage caused directly or in-
  46. ;    directly by this code. Still, every released version is thouroughly
  47. ;    tested with Mungwall and Enforcer, official Commodore debugging tools.
  48. ;    These programs traps writes to unallocated ram and reads/writes to/from
  49. ;    non-ram memory areas, which should cover most bugs.
  50. ;
  51. ;    HISTORY:
  52. ;
  53. ;v1.0    Based on an article in AM/FM #11 by Teijo Kinuunen. Simple thing with
  54. ;    preset playback rate. Soundeffects length has to be a multiple of
  55. ;    SFX__BuffSize.
  56. ;
  57. ;v1.1    Upvamped version.
  58. ;    * Selectable playback rate. (No big deal)
  59. ;    * Mastervolume.
  60. ;
  61. ;v1.2    Threw the original mixing scheme out.
  62. ;    * Fixed a bug where the interrupt sometimes didn't fill the entire
  63. ;      output-buffer. (Clicks and distorted sound could occur!)
  64. ;    * The end-of-sound detection was a bit buggy. Fixed.
  65. ;    * Earlier there was some problems with the sound not always appearing
  66. ;      when running SoundFX for the first time. This _seems_ to be fixed.
  67. ;    * Included fast mode. (Max 246/248 in playback rate!)
  68. ;    * Added SFX_StopSound().
  69. ;    * Optimized mixing a lot.
  70. ;    * SoundFX did not stop when errors occured. Now errors are properly
  71. ;      signalled.
  72. ;    * Did some alterations to make the source more portable. (Stopped using
  73. ;      includes and my personal macros.)
  74. ;    * Uses Disable()/Enable() instead of some bogus macros to disable
  75. ;      interrupts.
  76. ;    * Added non-interrupt mode, to make it possible to mix the channels
  77. ;      within a vertical-blank interrupt.
  78. ;
  79. ;    TODO:
  80. ;
  81. ;* Expand to 2 channels/4 voices. (optional)
  82. ;
  83. ;------------------------------------------------------------------------------
  84. ;
  85. ;    CONSTANTS:
  86. ;
  87. ;Constant:    SFX__BuffSize(INTEGER)
  88. ;Purpose:    Specifies the size of SoundFXs output buffer. The number should
  89. ;        be even. A large value causes less overhead by the interrupt
  90. ;        code but uses more memory for the buffers.
  91. ;
  92. ;Constant:    SFX__FastMode(BOOL)
  93. ;Purpose:    If set to non-zero, the fastmode will be enabled. The fastmode
  94. ;        provides faster mixing but is only capable of playing samples
  95. ;        at half the normal rates. Please also note that the sounddata
  96. ;        does not need to be halved when using the fastmode. This mixing
  97. ;        mode may produce high-frequency tones which may both distort
  98. ;        the sound and destroy loudspeakers! To get rid of this extra-
  99. ;        feature, enable the audio filter. :)
  100. ;
  101. ;Constant:    SFX__Debug(BOOL)
  102. ;Purpose:    If set to true, colors will be used to display CPU usage for
  103. ;        mixing loop.
  104. ;
  105. ;Constant:    SFX__Mode(BOOL)
  106. ;Purpose:    Selects the mode for SoundFX to run in. Modes are:
  107. ;        0 - User vertical blank. SoundFX will be set up for vertical
  108. ;            blank operation, but relies on the user to call
  109. ;            SFX_VBLHandle() each vertical blank.
  110. ;        1 - OS AudioInterrupt. SoundFX installs the interrupt itself
  111. ;            using the operating system.
  112. ;        Vertical blank modes needs you to carefully pick the buffersize
  113. ;        so that it's just about finished playing in one frame.
  114. ;
  115. ;    PUBLIC FUNCTIONS:
  116. ;
  117. ;Function:    SFX_Init(Rate)(D0)
  118. ;Purpose:    Initalize the routine and install audio-interrupt. Remember
  119. ;        that when the fastmode is enabled the actual sample playback
  120. ;        frequence will be half of what you state. Maximum values are
  121. ;        123 for PAL and 124 for NTSC. Remember to double these figures
  122. ;        when using the fastmode.
  123. ;
  124. ;Function:    SFX_End()
  125. ;Purpose:    Remove our audio interrupt and free any allocated resources.
  126. ;
  127. ;Function:    SFX_StartSound(Partition,Wave,Waveend)(D0,A0,A1)
  128. ;Purpose:    Start playing the selected sound. The sounddata should be
  129. ;        halved if the fastmode is disabled.
  130. ;
  131. ;Function:    SFX_StopSound(Partition)(D0)
  132. ;Purpose:    Stops the current sound.
  133. ;
  134. ;Function:    SFX_SetVolume(Volume.w (0-64))(D0)
  135. ;Purpose:    Alters the playback volume. Use for fading.
  136. ;
  137. ;    PRIVATE FUNCTIONS:
  138. ;
  139. ;Function:    SFX_VBLInit()
  140. ;Purpose:    Initializes SoundFX for use without using the audio interrupt.
  141. ;
  142. ;Function:    SFX_VBLEnd()
  143. ;Purpose:    Closes down SoundFX when audio interrupt hasn't been used.
  144. ;
  145. ;Function:    SFX_VBLHandle()
  146. ;        Does the actuall stuff when SoundFX is run in VBL-mode.
  147. ;
  148. ;Function:    SFX_AudIntInit()
  149. ;Purpose:    Initializes the audio interrupt handler.
  150. ;
  151. ;Function:    SFX_AudIntEnd()
  152. ;Purpose:    Closes down the audio interrupt handler.
  153. ;
  154. ;Function:    SFX_AudInt()
  155. ;Purpose:    This is the interrupt-handler for SoundFX when running in audio
  156. ;        interrupt mode.
  157. ;
  158. ;Function:    SFX_DoMix()
  159. ;Purpose:    Does actual mixing.
  160. ;
  161. ;------------------------------------------------------------------------------
  162.  
  163. ; Set all undefined constants to default values. If you dont't like 'em, feel
  164. ; free to change, though you'll have to do it all over for each new version.
  165.  
  166.     ifnd SFX__BuffSize
  167. SFX__BuffSize    =    1024            ; 16-131072
  168.     endc
  169.  
  170.     ifnd SFX__FastMode
  171. SFX__FastMode    =    0            ; BOOL
  172.     endc
  173.  
  174.     ifnd SFX__Debug
  175. SFX__Debug    =    0            ; BOOL
  176.     endc
  177.  
  178.     ifnd SFX__Mode
  179. SFX__Mode    =    1            ; BOOL
  180.     endc
  181.  
  182.     rsreset    ; Voice data
  183. vd_StartPtr    rs.l    1            ; Start of data, CHIP
  184. vd_EndPtr    rs.l    1            ; End of data, CHIP
  185. vd_Active    rs.l    1
  186. vd_sizeof    rs.b    0
  187.  
  188. SFX_WAITDMA    macro
  189.         move.w    $dff006,d1
  190.         moveq.l    #80-1,d0
  191. .DMALoop1    cmp.w    $dff006,d1
  192.         beq.s    .DMALoop1
  193.         move.w    $dff006,d1
  194. .DMALoop2    cmp.w    $dff006,d1
  195.         beq.s    .DMALoop2
  196.         move.w    $dff006,d1
  197.            dbf    d0,.DMALoop1
  198.         endm
  199.  
  200. ;------------------------------------------------------------------------------
  201. ;==                INIT                         ==
  202. ;------------------------------------------------------------------------------
  203. SFX_Init
  204.     ifne SFX__FastMode
  205.         lsr.l    #1,d0        ; Double playback rate
  206.     endc
  207.  
  208.         move.w    d0,SFX_PlayRate
  209.  
  210.         moveq.l    #0,d0
  211.         bsr.w    SFX_StopSound        ; Play no sound.
  212.  
  213.         moveq.l    #1,d0
  214.         bsr.w    SFX_StopSound        ; Play no sound.
  215.  
  216.         lea    SFX_AudioBuff,a0
  217.         move.w    #SFX__BuffSize-1,d1
  218. .ClrLoop    clr.w    (a0)+            ; Clear track buffers
  219.         dbf    d1,.ClrLoop
  220.  
  221.         clr.b    SFX_WhichBuffer        ; Buffer flag
  222.  
  223.     ifeq SFX__Mode
  224.         bsr.w    SFX_VBLInit
  225.     endc
  226.     ifeq SFX__Mode-1
  227.         bsr.w    SFX_AudIntInit
  228.     endc
  229.         beq.s    .Err
  230.  
  231.         moveq.l    #1,d0
  232.         rts
  233.  
  234. .Err        bsr.s    SFX_End
  235.         moveq    #0,d0
  236.         rts
  237.  
  238. ;------------------------------------------------------------------------------
  239. ;==                END                         ==
  240. ;------------------------------------------------------------------------------
  241. SFX_End
  242.     ifeq SFX__Mode
  243.         bsr.w    SFX_VBLEnd
  244.     endc
  245.     ifeq SFX__Mode-1
  246.         bsr.w    SFX_AudIntEnd
  247.     endc
  248.  
  249.         rts
  250.  
  251. ;------------------------------------------------------------------------------
  252. ;==                SETVOLUME                     ==
  253. ;------------------------------------------------------------------------------
  254. SFX_SetVolume    move.w    d0,$dff0d8
  255.         move.w    d0,SFX_Volume
  256.         rts
  257.  
  258. ;------------------------------------------------------------------------------
  259. ;==                STARTSOUND                     ==
  260. ;------------------------------------------------------------------------------
  261. SFX_StartSound    tst.l    d0
  262.         beq.s    .Zero
  263.  
  264.         lea    SFX_PartitionB,a2
  265.         move.l    a0,vd_StartPtr(a2)    ; Init ptr
  266.         move.l    a1,vd_EndPtr(a2)    ; Init endptr
  267.         move.l    #1,vd_Active(a2)
  268.  
  269.         rts
  270.  
  271. .Zero        lea    SFX_PartitionA,a2
  272.         move.l    a0,vd_StartPtr(a2)    ; Init ptr
  273.         move.l    a1,vd_EndPtr(a2)    ; Init endptr
  274.         move.l    #1,vd_Active(a2)
  275.  
  276.         rts
  277.  
  278. ;------------------------------------------------------------------------------
  279. ;==                STOPSOUND                     ==
  280. ;------------------------------------------------------------------------------
  281. SFX_StopSound    tst.l    d0
  282.         beq.s    .Zero
  283.  
  284.         lea    SFX_PartitionB,a2
  285.         move.l    #SFX_ZeroData,vd_StartPtr(a2)    ; Init startptr
  286.         move.l    #SFX_ZeroData+SFX__BuffSize,vd_EndPtr(a2); Init endptr
  287.         move.l    #0,vd_Active(a2)
  288.  
  289.         rts
  290.  
  291. .Zero        lea    SFX_PartitionA,a2
  292.         move.l    #SFX_ZeroData,vd_StartPtr(a2)    ; Init startptr
  293.         move.l    #SFX_ZeroData+SFX__BuffSize,vd_EndPtr(a2); Init endptr
  294.         move.l    #0,vd_Active(a2)
  295.  
  296.         rts
  297.  
  298.     ifeq SFX__Mode
  299.  
  300. ;------------------------------------------------------------------------------
  301. ;==                VBL INIT                     ==
  302. ;------------------------------------------------------------------------------
  303. SFX_VBLInit    lea    $dff000,a0
  304.  
  305.         move.w    #$0008,$96(a0)        ; dmacon (disable audio)
  306.         move.l    #$0400,$9a(a0)        ; intena (disable audio)
  307.  
  308.         move.w    #SFX__BuffSize/2,aud3+ac_len(a0); Buffer size
  309.         move.w    #65535,aud3+ac_per(a0)        ; Period
  310.         move.l    #SFX_AudioBuff,aud3+ac_ptr(a0)    ; Pointer
  311.         move.w    SFX_Volume,aud3+ac_vol(a0)    ; Volume
  312.  
  313.         SFX_WAITDMA
  314.  
  315.         move.w    #$8008,$96(a0)        ; dmacon (enable audio)
  316.  
  317.         moveq.l    #1,d0
  318.         rts
  319.  
  320. ;------------------------------------------------------------------------------
  321. ;==                VBL END                         ==
  322. ;------------------------------------------------------------------------------
  323. SFX_VBLEnd    move.w    #$0008,$dff096
  324.         rts
  325.  
  326. ;------------------------------------------------------------------------------
  327. ;==            VBL FRAMEHANDLER                     ==
  328. ;------------------------------------------------------------------------------
  329. SFX_VBLFrame    lea.l    SFX_AudioBuff,a1
  330.         not.b    SFX_WhichBuffer        ; Swap buffer
  331.         beq.s    .SetBuff
  332.  
  333. .UseBuff1    lea.l    SFX__BuffSize(a1),a1    ; Get next buffer
  334.  
  335. .SetBuff    lea.l    $dff000,a0
  336.  
  337.         move.w    #$0008,$96(a0)        ; dmacon (disable audio)
  338.  
  339.         move.w    #SFX__BuffSize/2,aud3+ac_len(a0); Buffer size
  340.         move.w    SFX_PlayRate,aud3+ac_per(a0)    ; Period
  341.         move.l    a1,aud3+ac_ptr(a0)        ; Pointer
  342.         move.w    SFX_Volume,aud3+ac_vol(a0)    ; Volume
  343.  
  344.         SFX_WAITDMA
  345.  
  346.         move.w    #$8008,$96(a0)        ; dmacon (enable audio)
  347.  
  348.         bsr.s    SFX_DoMix
  349.  
  350.         rts
  351.  
  352.     endc
  353.  
  354.     ifeq SFX__Mode-1
  355.  
  356. ;------------------------------------------------------------------------------
  357. ;==            AUDIOINTERRUPT INIT                     ==
  358. ;------------------------------------------------------------------------------
  359. SFX_AudIntInit    moveq    #10,d0            ; INTB_AUD3
  360.         lea    SFX_AudIntReq,a1
  361.         move.l    4.w,a6
  362.         jsr    -162(a6)        ; _LVOSetIntVector
  363.  
  364.         move.l    d0,SFX_PrevAudInt
  365.         beq.w    .Err
  366.  
  367.         lea    $dff000,a0
  368.         move.w    #SFX__BuffSize/2,$d4(a0); Buffer size
  369.         move.w    #65535,$d6(a0)        ; Period
  370.         move.l    #SFX_AudioBuff,$d0(a0)    ; Pointer
  371.         move.w    SFX_Volume,$d8(a0)    ; Volume
  372.  
  373.         lea    $dff000,a0
  374.         move.w    #$4000,$9a(a0)
  375.  
  376.         move.l    4.w,a6
  377.         jsr    -120(a6)        ; _LVODisable
  378.  
  379.         lea    $dff000,a0
  380.         move.w    #$0008,$96(a0)        ; Audio DMA off
  381.         move.w    #$8400,$9a(a0)        ; Enable sound interrupt
  382.         move.w    #$c000,$9a(a0)
  383.         move.w    #$8008,$96(a0)        ; DMA Audio channel 3 ON
  384.  
  385.         move.l    4.w,a6
  386.         jsr    -126(a6)        ; _LVOEnable
  387.  
  388.         moveq.l    #1,d0
  389.         rts
  390.  
  391. .Err        moveq.l    #0,d0
  392.         rts
  393.  
  394. ;------------------------------------------------------------------------------
  395. ;==            AUDIOINTERRUPT END                     ==
  396. ;------------------------------------------------------------------------------
  397. SFX_AudIntEnd    tst.b    SFX_IfPlay
  398.         beq.s    .NoPlay
  399.  
  400.         move.w    #1<<10,$dff09a
  401.         move.w    #$8,$dff096
  402.         clr.b    SFX_IfPlay
  403.  
  404. .NoPlay        move.l    SFX_PrevAudInt,d0
  405.         beq.s    .NoInt            ; Any interrupt?
  406.  
  407.         move.l    #0,SFX_PrevAudInt    ; Clear interrupt
  408.         move.w    #1<<10,$dff09a        ; intena
  409.         move.l    d0,a1
  410.         moveq    #10,d0
  411.         move.l    4.w,a6
  412.         jsr    -162(a6)        ; _LVOSetIntVector
  413.  
  414. .NoInt        move.w    #$0008,$dff096        ; Stop Audio DMA
  415.  
  416.         rts
  417.  
  418. ;------------------------------------------------------------------------------
  419. ;==                INTHANDLER                     ==
  420. ;------------------------------------------------------------------------------
  421. SFX_AudInt    movem.l    d2-a0/a2-a6,-(sp)
  422.  
  423.         not.b    SFX_WhichBuffer        ; Swap buffer
  424.         beq.s    .SetBuff
  425.  
  426. .UseBuff1    lea.l    SFX__BuffSize(a1),a1    ; Get next buffer
  427.  
  428. .SetBuff    lea.l    $dff000,a0
  429.         move.l    a1,$d0(a0)
  430.  
  431.          move.w    #SFX__BuffSize/2,$d4(a0); Buffer size
  432.         move.w    SFX_PlayRate,$d6(a0)    ; Period
  433.         move.w    SFX_Volume,$d8(a0)    ; Volume
  434.  
  435.         move.w    #1<<10,$9c(a0)        ; Clear intreq bit
  436.  
  437.         bsr.s    SFX_DoMix
  438.  
  439.         moveq.l    #0,d0
  440.  
  441.         movem.l    (sp)+,d2-a0/a2-a6
  442.         rts
  443.  
  444.     endc
  445.  
  446. ;------------------------------------------------------------------------------
  447. ;==                DOMIX                         ==
  448. ;------------------------------------------------------------------------------
  449. SFX_DoMix
  450.     ifne SFX__Debug
  451.         move.w    #$fff,$dff180
  452.     endc
  453.  
  454.         lea.l    SFX_PartitionA,a3
  455.  
  456.         tst.l    vd_Active(a3)        ; Addvalue
  457.         beq.s    .AOk
  458.  
  459.     ifeq SFX__FastMode
  460.         add.l    #SFX__BuffSize,vd_StartPtr(a3)    ; Next chunk
  461.         move.l    (a3),d7            ; Fetch ptr
  462.         add.l    #SFX__BuffSize,d7
  463.         cmp.l    vd_EndPtr(a3),d7    ; Will we break?
  464.         bls.s    .AOk
  465.     else
  466.         add.l    #SFX__BuffSize/2,vd_StartPtr(a3); Next chunk
  467.         move.l    (a3),d7            ; Fetch ptr
  468.         add.l    #SFX__BuffSize/2,d7
  469.         cmp.l    vd_EndPtr(a3),d7    ; Will we break?
  470.         bls.s    .AOk
  471.     endc
  472.  
  473.         clr.l    vd_Active(a3)        ; Stop sound
  474.         move.l    #SFX_ZeroData,vd_StartPtr(a3)
  475.         move.l    #SFX_ZeroData+SFX__BuffSize,vd_EndPtr(a3)
  476.  
  477. .AOk        lea.l    SFX_PartitionB,a4
  478.  
  479.         tst.l    vd_Active(a4)        ; Addvalue
  480.         beq.s    .BOk
  481.  
  482.     ifeq SFX__FastMode
  483.         add.l    #SFX__BuffSize,vd_StartPtr(a4)    ; Next chunk
  484.         move.l    (a4),d7            ; Fetch ptr
  485.         add.l    #SFX__BuffSize,d7
  486.         cmp.l    vd_EndPtr(a4),d7    ; Will we break?
  487.         bls.s    .BOk
  488.     else
  489.         add.l    #SFX__BuffSize/2,vd_StartPtr(a4)    ; Next chunk
  490.         move.l    (a4),d7            ; Fetch ptr
  491.         add.l    #SFX__BuffSize/2,d7
  492.         cmp.l    vd_EndPtr(a4),d7    ; Will we break?
  493.         bls.s    .BOk
  494.     endc
  495.  
  496.         clr.l    vd_Active(a4)        ; Stop sound
  497.         move.l    #SFX_ZeroData,vd_StartPtr(a4)
  498.         move.l    #SFX_ZeroData+SFX__BuffSize,vd_EndPtr(a4)
  499.  
  500. .BOk        move.l    vd_StartPtr(a3),a3    ; Get startaddress A
  501.         move.l    vd_StartPtr(a4),a4    ; Get startaddress B
  502.  
  503.     ifeq SFX__FastMode
  504.         move.l    #SFX__BuffSize-1,d5
  505.     else
  506.         move.l    #(SFX__BuffSize/2)-1,d5
  507.     endc
  508. .MixLoop
  509.  
  510.     ifeq SFX__FastMode
  511.         move.b    (a3)+,d4        ; Get sample 1
  512.         add.b    (a4)+,d4        ; Add sample 2
  513.         move.b    d4,(a1)+        ; Store value in buffer.
  514.     else
  515.         move.b    (a3)+,(a1)+        ; Get sample 1
  516.         move.b    (a4)+,(a1)+        ; Get sample 2
  517.     endc
  518.  
  519.         dbf    d5,.MixLoop
  520.  
  521.     ifne SFX__Debug
  522.         move.w    #0,$dff180
  523.     endc
  524.         rts
  525.  
  526. ;------------------------------------------------------------------------------
  527.  
  528.     SECTION    MiscData,DATA
  529.  
  530. SFX_ZeroData    dcb.b    SFX__BuffSize,0
  531.     EVEN
  532.  
  533. SFX_PartitionA    dcb.b    vd_sizeof,0
  534. SFX_PartitionB    dcb.b    vd_sizeof,0
  535.  
  536.     ifeq SFX__Mode-1
  537.  
  538. SFX_AudIntReq    dc.l    0,0            ; SUCC, PRED
  539.         dc.b    2            ; NT_INTERRUPT
  540.         dc.b    0
  541.         dc.l    .IntName
  542.  
  543.         dc.l    SFX_AudioBuff
  544.         dc.l    SFX_AudInt,0
  545. .IntName    dc.b    "SoundFX audioint",0
  546.     EVEN
  547. SFX_PrevAudInt    dc.l    0
  548.  
  549.     endc
  550.  
  551. SFX_PlayRate    dc.w    0
  552. SFX_Volume    dc.w    64
  553. SFX_IfPlay    dc.b    0
  554. SFX_WhichBuffer    dc.b    0
  555.  
  556.  
  557.     SECTION ChipData,DATA_C
  558.  
  559. SFX_AudioBuff    ds.b    SFX__BuffSize*2        ; Two buffers
  560.  
  561.     SECTION Samples,DATA
  562.  
  563. ; Your samples. Locate in fast if possible!
  564.  
  565.     INCDIR    "!Sources:Utility/"
  566.  
  567. Sample1    INCBIN    SAMPLE1
  568.     dcb.b    64,0
  569. Sample1End
  570.  
  571. Sample2    INCBIN    SAMPLE2
  572.     dcb.b    416,0
  573. Sample2End
  574.  
  575.     END
  576.  
  577.